/**
 * 
 */
package name.shamansir.tadah.data;

import java.util.Arrays;

import android.text.format.Time;

import name.shamansir.tadah.data.Tag.Type;
import name.shamansir.tadah.data.scheduling.Occurrence;
import name.shamansir.tadah.data.scheduling.Run;
import name.shamansir.tadah.data.scheduling.rules.OccursSingleTime;
import name.shamansir.tadah.data.scheduling.rules.RepeatsAmountOfPeriod;
import name.shamansir.tadah.data.scheduling.rules.RepeatsByMinutes;
import name.shamansir.tadah.data.scheduling.rules.RepeatsByWeekdays;
import name.shamansir.tadah.data.scheduling.rules.RepeatsDatesInYear;
import name.shamansir.tadah.data.scheduling.rules.RepeatsDaysInMonth;
import name.shamansir.tadah.data.scheduling.rules.RepeatsEveryDay;
import name.shamansir.tadah.data.scheduling.rules.RepeatsMonthsInYear;
import name.shamansir.tadah.data.scheduling.rules.RepeatsOddOrEvenDays;

/**
 * <dl>
 * <dt>Project:</dt> <dd>ta-dah</dd>
 * <dt>Package:</dt> <dd>name.shamansir.tadah.data</dd>
 * </dl>
 *
 * <code>TodoBuilder</code>
 *
 * <p>Description</p>
 *
 * @author Ulric Wilfred <shaman.sir@gmail.com>
 * @date May 31, 2011 7:41:19 PM 
 *
 */
public class TodoBuilder {
    
    //public final String LOG_TAG = "TodoBuilder";
    
    private TodoItem item;
    
    public TodoBuilder() {
        this(new TodoItem());
    }
    
    public TodoBuilder(TodoItem source) {
        this.item = source;
    }
    
    // title, body, priority
    
    public TodoBuilder title(String title) {
        item.changeTitle(title);
        return this;
    }
    
    public TodoBuilder body(String body) {
        item.changeBody(body);
        return this;
    }
    
    public TodoBuilder priority(int priority) {
        item.changePriority(priority);
        return this;
    }
    
    // tags
    
    public TodoBuilder tag(String tag) {
        item.addTag(tag);
        return this;
    }
    
    public TodoBuilder tag(String tag, Type type) {
        item.addTag(type, tag);
        return this;
    }
        
    public TodoBuilder tags(String... tags) {
        for (String tag: tags) {
            item.addTag(tag);
        }
        return this;
    }
    
    public TodoBuilder tags(Type type, String... tags) {
        for (String tag: tags) {
            item.addTag(type, tag);
        }
        return this;
    }
        
    // projects. locations    
    
    public TodoBuilder project(String project) {
        item.addTag(Type.PROJECT, project);
        return this;
    }
    
    public TodoBuilder projects(String... projects) {
        return tags(Type.PROJECT, projects);
    }    
    
    public TodoBuilder location(String location) {
        item.addTag(Type.LOCATION, location);
        return this;
    }
    
    public TodoBuilder locations(String... locations) {
        return tags(Type.PROJECT, locations);
    }
    
    // children    
    
    public TodoBuilder child(TodoItem child) {
        item.addChild(child);
        return this;
    }
    
    public TodoBuilder children(TodoItem... children) {
        item.addChildren(Arrays.asList(children));
        return this;
    }
    
    // started, in progress, done

    public TodoBuilder started() {
        Time now = new Time(); now.setToNow();        
        return started(now);
    }
    
    public TodoBuilder started(Time from) {
        Time now = new Time(); now.setToNow();        
        Time end = item.hasProgress()
                   ? item.getProgress().getEnd()
                   : null;
        item.setProgress(new Run(from, end));
        return this;
    }    
    
    public TodoBuilder inProgress(Time from, Time to) {
        item.setProgress(new Run(from, to));
        return this;
    }
    
    public TodoBuilder inProgress(Run run) { 
        item.setProgress(run);
        return this;
    }
    
    public TodoBuilder done() {
        Time now = new Time(); now.setToNow();
        return done(now);
    }    
    
    public TodoBuilder done(Time when) {
        Time start = item.hasProgress()
                     ? item.getProgress().getStart()
                     : null;
        item.setProgress(new Run(start, when));
        return this;
    }
    
    // scheduling
    // - occurs once
    
    public TodoBuilder occurs(Time time) {
        item.addRule(new OccursSingleTime().setTime(time));
        return this;
    }
    
    public TodoBuilder occurs(int day, int month, int year) {
        item.addRule(new OccursSingleTime().setDate(day, month, year));
        return this;
    }
    
    public TodoBuilder occurs(Time start, Time end) {
        item.addRule(new OccursSingleTime().setRun(start, end));
        return this;
    }
    
    public TodoBuilder occurs(Run run) {
        item.addRule(new OccursSingleTime().setRun(run));
        return this;
    }
    
    public TodoBuilder longsFor(int amount, Occurrence period) {
        Time now = new Time(); now.setToNow();
        Time start = item.hasProgress()
                     ? item.getProgress().getStart()
                     : now;
        item.setProgress(Run.byDuration(start, amount, period));
        return this;
    }    
    
    // - repeats amount of period
    
    public TodoBuilder repeats(int amount, Occurrence period) {
        item.addRule(new RepeatsAmountOfPeriod().addSpec(amount, period.ordinal()));
        return this;
    }
    
    // - repeats at concrete time
    
    
    public TodoBuilder repeatsAt(Time... time) {
        item.addRule(new RepeatsEveryDay().addTime(time));
        return this;        
    }
    
    // - repeats by minutes
    
    public TodoBuilder repeatsMinutes(int... minutes) {
        item.addRule(new RepeatsByMinutes().addMinutes(minutes));
        return this;
    }
    
    // - repeats by weekdays
    
    public TodoBuilder repeatsWeekdays(int... weekdays) {
        item.addRule(new RepeatsByWeekdays().addWeekdays(weekdays));
        return this;
    }
    
    // - repeats dates in year
    
    public TodoBuilder repeatsDates(Time... dates) {
        item.addRule(new RepeatsDatesInYear().addDates(dates));
        return this;        
    }
    
    // - repeats days in month
    
    public TodoBuilder repeatsDays(int... days) {
        item.addRule(new RepeatsDaysInMonth().addDates(days));
        return this;
    }
    
    // - repeats months in year
    
    public TodoBuilder repeatsMonths(int... months) {
        item.addRule(new RepeatsMonthsInYear().addMonths(months));
        return this;
    }
    
    // - repeats odd or even days
    
    public TodoBuilder repeatsOddDays() {
        item.addRule(new RepeatsOddOrEvenDays().odd());
        return this;
    }
    
    public TodoBuilder repeatsEvenDays() {
        item.addRule(new RepeatsOddOrEvenDays().even());
        return this;
    }    
    
    // - repeats by complex conditions
    
    // TODO: implement
    
    // build
    
    public TodoItem build() {
        item.validateScheduling();
        return item;
    }
    
    public TodoBuilder reset() {
        item = new TodoItem();
        return this;
    }

}
